package com.wang.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.mall.bean.*;
import com.wang.mall.mapper.ProductMapper;
import com.wang.mall.service.OmsOrderService;
import com.wang.mall.service.ProductImageService;
import com.wang.mall.service.ProductService;
import com.wang.mall.to.rabbitmq.StockDetailTo;
import com.wang.mall.to.rabbitmq.StockLockedTo;
import com.wang.mall.util.PageUtils;
import com.wang.mall.vo.LockStockResult;
import com.wang.mall.vo.OrderItemVo;
import com.wang.mall.vo.WareProductLockVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class
ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {


    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ProductImageService productImageService;

    @Override
    public PageUtils queryPage(Integer page, Integer limit, String productName) {

        IPage<Product> page1 = page(new Page<Product>(page, limit), new LambdaQueryWrapper<Product>().like(!StringUtils.isEmpty(productName), Product::getName, productName));

        List<Product> records = page1.getRecords();
        List<Product> collect = records.stream().map(product -> {
            List<ProductImage> list = productImageService.list(new LambdaQueryWrapper<ProductImage>().eq(ProductImage::getProductId, product.getId()));
            product.setImageList(list);
            return product;
        }).collect(Collectors.toList());


        page1.setRecords(collect);

        return new PageUtils(page1);
    }

    @Override
    @Transactional
    public boolean saveProduct(Product product) {
        boolean save = save(product);
        Integer id = product.getId();

        List<ProductImage> imageList = product.getImageList();
        List<ProductImage> collect = imageList.stream().map(img -> {
            img.setProductId(id);
            return img;
        }).collect(Collectors.toList());

        boolean b = productImageService.saveBatch(collect);
        return save && b;
    }

    @Override
    public Product getInfo(Long id) {
        Product product = getById(id);

        List<ProductImage> productImages = productImageService.list(new LambdaQueryWrapper<ProductImage>().eq(ProductImage::getProductId, id));
        product.setImageList(productImages);

        return product;
    }

    @Transactional
    @Override
    public boolean updateProduct(Product product) {
        boolean b = updateById(product);

        boolean remove = productImageService.remove(new LambdaQueryWrapper<ProductImage>().eq(ProductImage::getProductId, product.getId()));

        List<ProductImage> collect = product.getImageList().stream().map(img -> {
            img.setProductId(product.getId());
            return img;
        }).collect(Collectors.toList());

        boolean b1 = productImageService.saveBatch(collect);

        return b && b1;
    }

    @Transactional
    @Override
    public boolean delete(List<Long> ids) {
        boolean b = removeByIds(ids);
        boolean remove = productImageService.remove(new LambdaQueryWrapper<ProductImage>().in(ProductImage::getProductId, ids));
        return b && remove;
    }

    /**
     * 判断商品是否有库存
     *
     * @param productIds
     * @return
     */
    @Override
    public List<Map<String, Object>> getProductsHasStock(List<Long> productIds) {
        return productIds.stream().map(item -> {
            Map<String, Object> longBooleanHashMap = new HashMap<>();
            Long count = baseMapper.getSkuStock(item);
            longBooleanHashMap.put("productId", item);
            longBooleanHashMap.put("hasStock", count > 0);
            return longBooleanHashMap;
        }).collect(Collectors.toList());
    }


    @Autowired
    WmsWareOrderTaskService wmsWareOrderTaskService;

    @Autowired
    WmsWareOrderTaskDetailService wmsWareOrderTaskDetailService;

    /**
     * 为订单锁定库存
     * 1.库存解锁
     * 1.下单成功,没有支付,自动取消,或者用户手动取消
     * 2. 下订单成功,库存锁定成功,接下来的业务调用失败,导致订单回滚
     * 之前锁定库存自动解锁
     *
     * @param lockVo
     * @return
     */
    @Transactional
    @Override
    public List<LockStockResult> orderLock(WareProductLockVo lockVo) {


        List<OrderItemVo> itemVos = lockVo.getLocks();
        String orderSn = lockVo.getOrderSn();


        // 库存工作单
        WmsWareOrderTask wmsWareOrderTask = new WmsWareOrderTask();
        wmsWareOrderTask.setOrderSn(orderSn);
        wmsWareOrderTaskService.save(wmsWareOrderTask);

        ArrayList<LockStockResult> lockStockResults = new ArrayList<>();

        boolean productStock = true;
        // 如果每一个商品锁定成功,将当前商品锁定的工单记录发送给ＭＱ
        // 如果锁定失败,前面保存的工作单信息就会滚了, 发送出去的消息,即使要解锁记录,由于去数据库查不到ID, 所以就不用解锁
        for (OrderItemVo itemVo : itemVos) {
            LockStockResult lockStockResult = new LockStockResult();

            Long productId = itemVo.getProductId();
            Integer count = itemVo.getCount();
            // 判断商品是否有库存
            Product product = getById(productId);
            // 修改商品锁定库存数量, 成功返回1, 否则返回0
            Long i = baseMapper.lockProductStock(product, count);
            // 库存锁定成功 i == 1   库存锁定失败 i == 0


            lockStockResult.setIsLock(i == 1);
            lockStockResult.setProductId(productId);
            lockStockResult.setNum(count);
            lockStockResults.add(lockStockResult);
            productStock = i == 1;
            if (i == 1) {
                // 保存每个商品的库存工作单
                WmsWareOrderTaskDetail wmsWareOrderTaskDetail = new WmsWareOrderTaskDetail();
                wmsWareOrderTaskDetail.setSkuId(itemVo.getProductId());
                wmsWareOrderTaskDetail.setSkuName(itemVo.getTitle());
                wmsWareOrderTaskDetail.setSkuNum(itemVo.getCount());
                wmsWareOrderTaskDetail.setTaskId(wmsWareOrderTask.getId());
                wmsWareOrderTaskDetail.setLockStatus(1);
                wmsWareOrderTaskDetailService.save(wmsWareOrderTaskDetail);


                // 库存锁定才成功 , 发送给rabbitMQ
                StockLockedTo lockedTo = new StockLockedTo();
                // 保存库存工单的ID
                lockedTo.setId(wmsWareOrderTask.getId());
                // 保存库存工单的详情
                StockDetailTo stockDetailTo = new StockDetailTo();
                BeanUtils.copyProperties(wmsWareOrderTaskDetail, stockDetailTo);
                lockedTo.setStockDetailTo(stockDetailTo);

                rabbitTemplate.convertAndSend("wang-stock-event-exchange",
                        "stock.locked", lockedTo);
            } else {
                // 库存锁定失败
                // throw new IllegalArgumentException("库存锁定失败");
            }
        }
        return lockStockResults;
    }


    @Autowired
    OmsOrderService omsOrderService;


    /**
     * 解锁库存
     * 1.下单成功,库存锁定成功, 接下来业务调用失败, 导致订单回滚
     * ,之前锁定的库存要自动解锁
     * 2.订单失败,本身就是由于商品没锁主
     *
     * @param stockLockedTo
     * @return
     */
    @Override
    public void releaseLockStock(StockLockedTo stockLockedTo) {

        // 获取库存工作单的ID
        Long id = stockLockedTo.getId();
        StockDetailTo stockDetailTo = stockLockedTo.getStockDetailTo();
        Long productId = stockDetailTo.getSkuId();
        // 解锁
        // 根据库存工单ID,查询数据库关于这个订单的锁定库存工单信息
        WmsWareOrderTaskDetail byId = wmsWareOrderTaskDetailService.getById(stockDetailTo.getId());
        if (byId != null) {
            // 1 有, 进行解锁,证明库存锁定成功了,要不要解锁还要看订单情况
            //  1.没有订单 , 一定要解锁
            //  2. 有这个订单,不是解锁库存
            //      看订单状态,
            //         已取消:解锁
            //         没取消, 不能解锁
            Long wareOrderTaskId = stockLockedTo.getId();
            WmsWareOrderTask wareOrderTask = wmsWareOrderTaskService.getById(wareOrderTaskId);
            String orderSn = wareOrderTask.getOrderSn();
            // 根据订单号查询订单状态
            OmsOrder omsOrder = omsOrderService.getOne(new LambdaQueryWrapper<OmsOrder>().eq(OmsOrder::getOrderSn, orderSn));
            if (omsOrder == null) {
                //1.没有订单 , 一定要解锁
                if (byId.getLockStatus() == 1) { // 库存工作单状态时已锁定未解锁,才能解锁
                    unLockStock(stockDetailTo.getSkuId(), stockDetailTo.getSkuNum(), stockDetailTo.getId());

                }
            } else {
                //  2. 有这个订单,不是解锁库存,而是看订单状态,
                //       状态码 4 订单已取消
                if (omsOrder.getStatus() == 4) {
                    //         已取消:解锁
                    // 查询库存工作单状态,  1-已锁定  2-已解锁  3-扣减
                    if (byId.getLockStatus() == 1) {
                        unLockStock(stockDetailTo.getSkuId(), stockDetailTo.getSkuNum(), stockDetailTo.getId());
                    }
                }
                //         没取消, 不用解锁
            }

        } else {
            // 2 没有,没有这个订单的库存信息, 库存就不用回滚了
        }
    }

    /**
     * 防止订单服务卡顿导致订单消息一直无法修改,
     * 库存消息优先到期,订单状态还是未支付,导致订单卡顿,无法解锁库存
     * 订单关闭, 解锁订单的库存
     *
     * @param omsOrder
     */
    @Transactional
    @Override
    public void releaseLockStock(OmsOrder omsOrder) {
        String orderSn = omsOrder.getOrderSn();
        // 查询最新的库存解锁状态,防止重新解锁库存
        WmsWareOrderTask orderTask = wmsWareOrderTaskService.getOne(new LambdaQueryWrapper<WmsWareOrderTask>().eq(WmsWareOrderTask::getOrderSn, orderSn));
        Long taskId = orderTask.getId();
        // 按照库存工作单查询, 状态为1 的库存工作单
        List<WmsWareOrderTaskDetail> orderTaskDetailList = wmsWareOrderTaskDetailService.list(new LambdaQueryWrapper<WmsWareOrderTaskDetail>()
                .eq(WmsWareOrderTaskDetail::getTaskId, taskId)
                .eq(WmsWareOrderTaskDetail::getLockStatus, 1));
        if (!CollectionUtils.isEmpty(orderTaskDetailList)) {
            for (WmsWareOrderTaskDetail wmsWareOrderTaskDetail : orderTaskDetailList) {
                //解锁库存
                unLockStock(wmsWareOrderTaskDetail.getSkuId(), wmsWareOrderTaskDetail.getSkuNum(), wmsWareOrderTaskDetail.getId());
            }
        }

    }

    /**
     * 解锁库存
     *
     * @param skuId  商品ID
     * @param skuNum 商品数量
     * @param id     库存工单项的ID
     */
    private void unLockStock(Long skuId, Integer skuNum, Long id) {

        int i = baseMapper.unLockStock(skuId, skuNum);


        // 更新库存工作单的状态 , 已解锁
        WmsWareOrderTaskDetail wmsWareOrderTaskDetail = new WmsWareOrderTaskDetail();
        wmsWareOrderTaskDetail.setId(id);
        wmsWareOrderTaskDetail.setLockStatus(2);
        wmsWareOrderTaskDetailService.updateById(wmsWareOrderTaskDetail);


    }


}
